package io.renren.modules.medicine.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.renren.common.annotation.DataFilter;
import io.renren.common.constant.Constant;
import io.renren.common.exception.RenException;
import io.renren.common.interceptor.DataScope;
import io.renren.common.page.PageData;
import io.renren.common.service.impl.CrudServiceImpl;
import io.renren.common.utils.JsonUtils;
import io.renren.common.validator.ValidatorUtils;
import io.renren.common.validator.group.AddGroup;
import io.renren.common.validator.group.DefaultGroup;
import io.renren.modules.medicine.dao.TaskProteinPredictionDao;
import io.renren.modules.medicine.dto.TaskProteinPredictionDTO;
import io.renren.modules.medicine.entity.TaskProteinPredictionEntity;
import io.renren.modules.medicine.service.TaskProteinPredictionService;
import io.renren.modules.security.user.SecurityUser;
import io.renren.modules.security.user.UserDetail;
import io.renren.modules.sys.service.SysDeptService;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;

/**
 * 蛋白质结构预测任务
 *
 * @author sheliming shelimingming@qq.com
 * @since 1.0.0 2022-12-03
 */
@Service
public class TaskProteinPredictionServiceImpl extends CrudServiceImpl<TaskProteinPredictionDao, TaskProteinPredictionEntity, TaskProteinPredictionDTO> implements TaskProteinPredictionService {

    @Autowired
    private SysDeptService sysDeptService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public QueryWrapper<TaskProteinPredictionEntity> getWrapper(Map<String, Object> params){
        String id = (String)params.get("id");
        QueryWrapper<TaskProteinPredictionEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(id), "id", id);
        wrapper.select(TaskProteinPredictionEntity.class, info -> !info.getColumn().equals("seq")
                && !info.getColumn().equals("pdb"));

        String beginTimeString = (String)params.get(Constant.BEGIN_TIME);
        wrapper.ge(StringUtils.isNotBlank(beginTimeString),"create_date",beginTimeString);
        String endTimeString = (String)params.get(Constant.END_TIME);
        wrapper.le(StringUtils.isNotBlank(endTimeString),"create_date",endTimeString);

        if(params.get(Constant.SQL_FILTER) != null){
            wrapper.apply(params.get(Constant.SQL_FILTER) != null, ((DataScope)params.get(Constant.SQL_FILTER)).getSqlFilter());
        }
        return wrapper;
    }


    @Override
    public void putTask(String seqString, Integer numMultimerPredictionsPerModel, Integer relaxation) {
        TaskProteinPredictionDTO dto = new TaskProteinPredictionDTO();
        dto.setNumMultimerPredictionsPerModel(numMultimerPredictionsPerModel);
        dto.setRelaxation(relaxation);
        dto.setSeq(seqString);

        UserDetail user = SecurityUser.getUser();
        dto.setCreator(user.getId());
        dto.setCreatorName(user.getRealName());
        dto.setUpdater(user.getId());
        dto.setDeptId(user.getDeptId());
        dto.setDeptName(sysDeptService.get(user.getDeptId()).getName());
        dto.setCreateDate(new Date());
        dto.setUpdateDate(new Date());
        dto.setPlddt(0.0f);
        dto.setStatus(0);
        //效验数据
        ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);

        this.save(dto);

        if (StringUtils.isEmpty(seqString)) {
            throw new RenException("seq文件是空");
        }
        String[] splits = seqString.split("\n");
        if (splits.length%2!=0) {
            throw new RenException("seq文件格式错误");
        }
        for(int i=0;i<numMultimerPredictionsPerModel;i++) {
            for(int j=0;j<splits.length/2;j++) {
                sendMQ(dto.getId(),splits[j*2],splits[j*2+1],relaxation);
            }
        }

        dto.setMsgCount(numMultimerPredictionsPerModel*(splits.length/2));
        dto.setStatus(1);
        this.update(dto);
    }

    private void sendMQ(Long taskId, String title, String seq, Integer relaxation) {
        MQBody mqBody = new MQBody();
        mqBody.setTaskId(taskId);
        mqBody.setTitle(title.startsWith(">")?title.substring(1):title);
        mqBody.setSeq(seq);
        mqBody.setRelaxation(relaxation);
        mqBody.setMethod("M2");
        mqBody.setAli("alignments");
        mqBody.setVersion("cairi_proteindesign");

        rabbitTemplate.convertAndSend("cairi_msa_exchange","cairi_msa.hh", JsonUtils.toJsonString(mqBody));
    }

    @Data
    private class MQBody{
        private Long taskId;
        private String title;
        private String seq;
        private Integer relaxation;
        private String method;
        private String ali;
        private String version;
    }
}